<?php


namespace app\common\service;

use app\common\enum\MainEnum;
use app\common\exception\ParameterFailedException;
use app\common\model\CouponModel;
use app\common\model\OrderListModel;
use app\common\model\OrderListRefundModel;
use app\common\model\OrderModel;
use app\common\model\PackageCompanyModel;
use app\common\model\UserCouponModel;
use app\common\model\UserOrderBrokerageModel;
use think\facade\Config;
use think\facade\Db;
use think\facade\Log;
use Yansongda\Pay\Pay as MainPay;

class Pay
{
    protected $config = [];

    public function __construct()
    {
        $this->config = Config::get('main.wx');
    }

    public function pay($nb, $price, $openid, $body)
    {
        $type = 'miniapp';
        //        mp	公众号支付	array $order	Collection
        //        wap	手机网站支付	array $order	Response
        //        app	APP 支付	array $order	JsonResponse
        //        pos	刷卡支付	array $order	Collection
        //        scan	扫码支付	array $order	Collection
        //        transfer	账户转账	array $order	Collection
        //        miniapp	小程序支付	array $order	Collection
        //        redpack	普通红包	array $order	Collection
        //        groupRedpack	裂变红包	array $order	Collection
        //Config::get('main.name')
        $order = [
            'out_trade_no' => $nb,
            'total_fee'    => $price * 100,
            #
            #1.01 $price
            // **单位：分**
            'body'         => $body,
            'openid'       => $openid,
            'notify_url'   => Config::get('main.wx.pay_notify_url'),
        ];

        //        vd(Config::get('main.wx'), $nb, $price, $openid, $body);

        switch ($type) {
            case 'miniapp':
                $pay = MainPay::wechat($this->config)
                    ->miniapp($order);
                return $pay->toArray();
            default:
                $pay = null;
        }

        // $pay->appId
        // $pay->timeStamp
        // $pay->nonceStr
        // $pay->package
        // $pay->signType
    }

    public function refund($nb, $refund_nb, $price, $refund_fee, $reason = '')
    {
        try {
            $type = 'miniapp';
            //        mp	公众号支付	array $order	Collection
            //        wap	手机网站支付	array $order	Response
            //        app	APP 支付	array $order	JsonResponse
            //        pos	刷卡支付	array $order	Collection
            //        scan	扫码支付	array $order	Collection
            //        transfer	账户转账	array $order	Collection
            //        miniapp	小程序支付	array $order	Collection
            //        redpack	普通红包	array $order	Collection
            //        groupRedpack	裂变红包	array $order	Collection
            /**
             * 'return_code' => string 'SUCCESS' (length=7)
             * 'return_msg' => string 'OK' (length=2)
             * 'appid' => string 'wxb3577ee5fac8bef0' (length=18)
             * 'mch_id' => string '1603840103' (length=10)
             * 'nonce_str' => string 'O6leMNEV0vxW1L1R' (length=16)
             * 'sign' => string '6B8C5E20EE063E972793BB998D141623' (length=32)
             * 'result_code' => string 'SUCCESS' (length=7)
             * 'transaction_id' => string '4200000814202011202665747271' (length=28)
             * 'out_trade_no' => string '20201120195fb7a2599c' (length=20)
             * 'out_refund_no' => string '20201120195fb7a2599crefund' (length=26)
             * 'refund_id' => string '50300706152020112204124729473' (length=29)
             * 'refund_channel' =>
             * array (size=0)
             * empty
             * 'refund_fee' => string '1' (length=1)
             * 'coupon_refund_fee' => string '0' (length=1)
             * 'total_fee' => string '1' (length=1)
             * 'cash_fee' => string '1' (length=1)
             * 'coupon_refund_count' => string '0' (length=1)
             * 'cash_refund_fee' => string '1' (length=1)
             */
            $order = [
                'out_trade_no'  => $nb,
                'out_refund_no' => $refund_nb,
                'total_fee'     => $price * 100,
                'refund_fee'    => $refund_fee * 100,
                'refund_desc'   => $reason,
                'type'          => $type,
                'notify_url'    => Config::get('main.wx.refund_notify_url'),
            ];
            switch ($type) {
                case 'miniapp':
                    $result = MainPay::wechat($this->config);
                    return $result->refund($order);
                default:
                    $pay = null;
            }
        } catch (\Exception $e) {
            throw new ParameterFailedException(['msg' => $e->getMessage()]);
        }
    }

    public function payNotify()
    {
        Db::startTrans();
        try {
            $pay = MainPay::wechat($this->config);
            /**
             * appid wxb3577ee5fac8bef0
             * bank_type OTHERS
             * cash_fee
             * fee_type CNY
             * is_subscribe N
             * mch_id 1603840103
             * nonce_str ErzqH0jfa17QC6ZE
             * openid opuUx5XdGPHFEFiaQEMKGZxmEY7Q
             * out_trade_no 20201120145fb76327a5
             * result_code SUCCESS
             * return_code SUCCESS
             * sign DFEBE583A2DBD1C94E32D2FEA751D49B
             * time_end 20201120143316
             * total_fee
             * trade_type JSAPI、NATIVE、APP   小程序JSAPI
             */
            $data = $pay->verify();
            Redis::getRedis()
                ->hSet('wx_notify_pay_success_temp', $data->out_trade_no, json_encode($data->all()));
            Redis::getRedis()
                ->zAdd('wx_notify_pay_success_all_temp', [], $data->success_time, json_encode($data->all()));
            new Email('1422476675@qq.com', 'lee', [
                'subject' => 'payNotify',
                'body'    => '详细代码：' . json_encode($data, JSON_FORCE_OBJECT),
            ]);
            //查出对应单号，状态
            $orderModel = (new OrderModel())->where('nb', $data->out_trade_no)
                ->where('status', MainEnum::ORDER_STATUS_WAIT_PAY)
                ->where('mch_id', $data->mch_id)
                ->where('price_pay', (float)($data->total_fee / 100))
                ->with([
                    'orderListInfo',
                    'userInfo' => ['platformInfo'],
                ])
                ->find();
            if ($orderModel) {
                $platformInfo = null;
                foreach ($orderModel->userInfo->platformInfo as $item) {
                    if ($item->getData('platform_specific') === $orderModel->getData('platform_specific')) {
                        $platformInfo = $item;
                        break;
                    }
                }
                if ($platformInfo) {
                    $pid                           = $platformInfo->getData('pid');
                    $ppid                          = $platformInfo->getData('ppid');
                    $prepareDataUserOrderBrokerage = [];
                    foreach ($orderModel->orderListInfo as $orderList) {
                        #比例分成 25%
                        $allMoney  = round(0.25 * $orderList->getData('price_pay'), 2);
                        $pidMoney  = round(0.8 * $allMoney, 2);
                        $ppidMoney = round($allMoney - $pidMoney, 2);
                        if ($pid && $pidMoney > 0) {
                            #pid
                            $prepareDataUserOrderBrokerage[] = [
                                'order_user_id'   => $orderModel->getData('user_id'),
                                'order_nb'        => $orderModel->getData('nb'),
                                'order_list_id'   => $orderList->getData('id'),
                                'order_pay_price' => $orderList->getData('price_pay'),
                                'brokerage_price' => $pidMoney,
                                'user_id'         => $pid,
                                'location'        => 1,
                                'status'          => MainEnum::USER_ORDER_BROKERAGE_STATUS['订单未完成'],
                            ];
                        }
                        if ($ppid && $ppidMoney > 0) {
                            #ppid
                            $prepareDataUserOrderBrokerage[] = [
                                'order_user_id'   => $orderModel->getData('user_id'),
                                'order_nb'        => $orderModel->getData('nb'),
                                'order_list_id'   => $orderList->getData('id'),
                                'order_pay_price' => $orderList->getData('price_pay'),
                                'brokerage_price' => $ppidMoney,
                                'user_id'         => $ppid,
                                'location'        => 2,
                                'status'          => MainEnum::USER_ORDER_BROKERAGE_STATUS['订单未完成'],
                            ];
                        }
                    }
                    (new UserOrderBrokerageModel())->saveAll($prepareDataUserOrderBrokerage);
                }
                $orderModel->pay_nb   = $data->transaction_id;
                $orderModel->pay_time = date('Y-m-d H:i:s', strtotime($data->time_end));
                $orderModel->pay_type = $data->trade_type;
                $orderModel->status   = MainEnum::ORDER_STATUS_WAIT_SHIPMENT;
                $orderModel->save();
                Redis::getRedis()
                    ->hSet('wx_notify_pay_success', $data->out_trade_no, json_encode($data->all()));
                Redis::getRedis()
                    ->zAdd('wx_notify_pay_success_all', [], $data->time_end, json_encode($data->all()));

                Db::commit();
                return $pay->success()
                    ->send();
            }
            Db::rollback();
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

    public function refundNotify()
    {
        Db::startTrans();
        try {
            $pay = MainPay::wechat($this->config);
            /**
             * appid wxb3577ee5fac8bef0
             * bank_type OTHERS
             * cash_fee
             * fee_type CNY
             * is_subscribe N
             * mch_id 1603840103
             * nonce_str ErzqH0jfa17QC6ZE
             * openid opuUx5XdGPHFEFiaQEMKGZxmEY7Q
             * out_trade_no 20201120145fb76327a5
             * result_code SUCCESS
             * return_code SUCCESS
             * sign DFEBE583A2DBD1C94E32D2FEA751D49B
             * time_end 20201120143316
             * total_fee
             * trade_type JSAPI、NATIVE、APP   小程序JSAPI
             * transaction_id 4200000819202011205318812460
             * transaction_id 4200000819202011205318812460
             * -------------------------------------------------------------
             * {"out_refund_no":"20201122135fb9f21e2b_refund",
             * "out_trade_no":"20201122135fb9f21e2b",
             * "refund_account":"REFUND_SOURCE_RECHARGE_FUNDS",
             * "refund_fee":"1","refund_id":"50300406092020112204125526519",
             * "refund_recv_accout":"\u652f\u4ed8\u7528\u6237\u96f6\u94b1",
             * "refund_request_source":"API",
             * "refund_status":"SUCCESS",
             * "settlement_refund_fee":"1",
             * "settlement_total_fee":"1",
             * "success_time":"2020-11-22 13:19:31",
             * "total_fee":"1",
             * "transaction_id":"4200000813202011225499571532",
             * "return_code":"SUCCESS",
             * "appid":"wxb3577ee5fac8bef0",
             * "mch_id":"1603840103",
             * "nonce_str":"550be2f2a3ea0eb9e3e1c879c04ca8d0",
             * "req_info":"YjRSVpaUvm8OXxknRNiYECkrgjxorbgmhmLV+Oiy\/wdlpBggVpcZFwZt7C1MPL2N6OXu8kLcWB7tbNNzrMxrgzPRNT1sgTIjMT38dfYbcatuVSTxhWYK9BGE2vQKx0GNuq8oAlc\/EwQJ48EX3J8h9XwFucdOaR7dO7mWEK7S8fUlweLqZoFSOkC5auJlmEO0jy1qUNmSOdQH8abgdjr5ZY9nCL0zl3bCUNQFYh9vBc3QcV\/JnHPwvyILY+LLsVQVD09hlZfnZsGQSRGILSgIYADcByA8WXhuAsMbD3y1DllOlLEPa3sY4BqKv3+YsEloda3S9q1ZnrqgEDdk89DfhlYecyObRF4VFJFmdnOzjphgdz6RUw3X1EhJf1fU\/JqN29jEDB6xXah6v7Pb0\/Fv5DMvI91IXISZkZh61EKReE8Jrl5lLj2AQSPaoGZDbLfQYaVw\/zWP1w4VRwjONpAjeE2i2HcrZmf4FX93sUYRPjX0F7Eg9qDWRvAfQPfrOQfqKAuVNT5dD5TKDl1WuyBjZb4JOcjY+vzo85mhARNGBPDek9J6BzMvlVGActFSMLE3taXlO3RAsyBZUTYHVV+S6JwxrmGUKfRMlqq+Y+Ba8xuddSICCco75olAcIW2OI\/eLHKoQCNzreMcFv2g\/NEMZN4pHiuSpmoszQnesZHIH3n\/6ZTl4TobL20tC+S9\/ZG9qHdx1omXQeAMQLJIMBES1tH3UFCHWlwN7e1lsqFgR2TOefvy132XrKh5Ll1H7v0jbGhu0vvqBhpZXqGcLmc+KKvxCy9RQlQ+vatZ4+ZnWvCyHmehx+C45bDWvyMA6ZOs2XgsgIDsbRjKsY2tI\/UJmPjj7WEAWUXVS4SfX\/9m1s95V\/gTUCTMb\/FVoy5VSsIG7vbnVVpb0hxHDS7Qm4rs0YVkSmRssaS3Tl3BTO9UyHCShAg8p4czktP5OFoCcXkf1gOanjFOm3McWEnD6sGtDGRG6RtpvsqgeKKzAkbYP8ZNM8xI93ENZvuO\/iEYRua8c5p3IXEOcv0AjoGGc\/l7ijzZVwpNeSTnrcriHGPk7WHsKAJ3jED1sYue4ShHWs2f"}
             */
            $data = $pay->verify(null, true);
            //            new Email('1422476675@qq.com', 'lee', [
            //                'subject' => 'refundNotify',
            //                'body'    => '详细代码：' . json_encode($data, JSON_FORCE_OBJECT),
            //            ]);
            Redis::getRedis()
                ->hSet('wx_notify_refund_success_temp', $data->out_trade_no, json_encode($data->all()));
            Redis::getRedis()
                ->zAdd('wx_notify_refund_success_all_temp', [], $data->success_time, json_encode($data->all()));
            //查询出该nb的所有refund
            $orderListRefundModel = (new OrderListRefundModel())->where('order_nb', $data->out_trade_no)
                ->select();
            if ($orderListRefundModel->isEmpty()) {
                throw new ParameterFailedException();
            }

            $ok = false;
            foreach ($orderListRefundModel as $item) {
                if ((string)$item->getData('refund_no') === (string)$data->out_refund_no && (int)$item->getData('status') === MainEnum::ORDER_LIST_REFUND_WAIT_PAY && (float)$item->getData('refund_fee') === (float)($data->refund_fee / 100)) {
                    $ok                          = true;
                    $item->pay_nb                = $data->transaction_id;
                    $item->pay_time              = date('Y-m-d H:i:s', strtotime($data->time_end));
                    $item->pay_type              = $data->trade_type;
                    $item->refund_status         = $data->refund_status;
                    $item->refund_request_source = $data->refund_request_source;
                    $item->refund_success_time   = date('Y-m-d H:i:s', strtotime($data->success_time));
                    $item->status                = MainEnum::ORDER_LIST_REFUND_DONE;
                    $item->save();
                    Redis::getRedis()
                        ->hSet('wx_notify_refund_success', $data->out_trade_no, json_encode($data->all()));
                    Redis::getRedis()
                        ->zAdd('wx_notify_refund_success_all', [], $data->time_end, json_encode($data->all()));

                }
            }

            if ($ok) {
                $orderListModels = (new OrderListModel())->where('order_nb', $data->out_trade_no)
                    ->select();
                $pass            = true;
                foreach ($orderListModels as $orderListModel) {
                    if ($orderListModel->getData('status') !== MainEnum::ORDER_LIST_REFUND_DONE) {
                        $pass = false;
                    }
                }
                if ($pass) {
                    $orderModel = (new OrderModel())->where('nb', $data->out_trade_no)
                        ->find();
                    if ($orderModel) {
                        //将订单状态改为已退款
                        $orderModel->status      = MainEnum::ORDER_STATUS_REFUND;
                        $orderModel->refund_time = NOW_TIME;
                        $orderModel->save();
                    }
                }

                Db::commit();
                return $pay->success()
                    ->send();
            }

            throw new ParameterFailedException();
            //            $orderListModels = (new self())->where('order_nb', $data['order_nb'])->select();
            //            $pass            = true;
            //            foreach ($orderListModels as $orderListModel) {
            //                if ($orderListModel->getData('status') !== MainEnum::ORDER_LIST_REFUND_DONE) {
            //                    if ($orderListModel->getData('id') === (int)$data['id'] && (int)$status === MainEnum::ORDER_LIST_REFUND_DONE) {
            //                        continue;
            //                    }
            //                    $pass = false;
            //                }
            //            }
            //            if ($pass) {
            //                (new OrderModel())->where('nb', $data['order_nb'])->save([
            //                    'status' => MainEnum::ORDER_STATUS_REFUND,
            //                ]);
            //            }


            //            if (count($orderListRefundModel) === 1) {
            //                //查看refund是不是只有一条，如果是并且退款，修改order的status
            //                foreach ($orderListRefundModel as $item) {
            //                    if ((int)$item->getData('status') === MainEnum::ORDER_LIST_REFUND_DONE) {
            //                        (new OrderModel())->where('nb', $data->out_trade_no)->save([
            //                            'status' => MainEnum::ORDER_STATUS_REFUND,
            //                        ]);
            //                        break;
            //                    }
            //                    break;
            //                }
            //            }
            //            elseif (count($orderListRefundModel) > 1) {
            //                //第二个过滤，查看是否全部的refund都已经退款了，如果是修改order的status
            //                $needChange = true;
            //                foreach ($orderListRefundModel as $item) {
            //                    if ($item->getData('status') !== MainEnum::ORDER_LIST_REFUND_DONE) {
            //                        $needChange = false;
            //                        break;
            //                    }
            //                }
            //                if ($needChange) {
            //                    (new OrderModel())->where('nb', $data->out_trade_no)->save([
            //                        'status' => MainEnum::ORDER_STATUS_REFUND,
            //                    ]);
            //                }
            //            }

        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
        //        $data = [];
        //        $data['transaction_id'];             #微信订单号 #4200000819202011205318812460
        //        $data['out_trade_no'];               #我方系统生成的订单号
        //        $data['refund_id'];                  #微信退款单号
        //        $data['out_refund_no'];              #商户退款单号
        //        $data['refund_fee'];                 #申请退款金额
        //        $data['settlement_refund_fee'];      #退款金额=申请退款金额-非充值代金券退款金额，退款金额<=申请退款金额
        //        /**
        //         * 退款状态
        //         * SUCCESS-退款成功
        //         * CHANGE-退款异常
        //         * REFUNDCLOSE—退款关闭
        //         */
        //        $data['refund_status'];
        //        $data['success_time']; #资金退款至用户帐号的时间，格式2017-12-15 09:46:01
        //        /**
        //         * 取当前退款单的退款入账方，例如：招商银行信用卡0403
        //         * 1）退回银行卡：
        //         * {银行名称}{卡类型}{卡尾号}
        //         * 2）退回支付用户零钱:
        //         * 支付用户零钱
        //         * 3）退还商户:
        //         * 商户基本账户
        //         * 商户结算银行账户
        //         * 4）退回支付用户零钱通:
        //         * 支付用户零钱通
        //         */
        //        $data['refund_recv_accout']; #退款入账账户
        //
        //        $data['total_fee'];                  #订单总金额，单位为分，只能为整数
    }

    public function aliPay($order = [])
    {
        //        $order = [
        //            'out_trade_no' => time(),
        //            'total_fee'    => '1',
        //            // **单位：分**
        //            'body'         => 'test body - 测试',
        //            'openid'       => 'onkVf1FjWS5SBIixxxxxxx',
        //        ];
        //        $pay   = MainPay::wechat(Env::get('main.ali'))->mp($order);

        // $pay->appId
        // $pay->timeStamp
        // $pay->nonceStr
        // $pay->package
        // $pay->signType
    }
}